// WTM默认页面 Wtm buidin page

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text.Json;
using System.Threading.Tasks;
using System.Web;
using HengTong.Model._Admin;
using HengTong.Model.Db;
using HengTong.Model.Db.Hr;
using HengTong.Model.Db.Other;
using HengTong.Model.Db.Other.Bill;
using HengTong.Model.Db.System;
using HengTong.Model.Request;
using HengTong.Model.Services;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using TiaoTaoHelper.Models;
using TiaoTaoHelper.Wtm.Attributes;
using TiaoTaoHelper.Wtm.Models;
using UUIDNext;
using WalkingTec.Mvvm.Core;
using WalkingTec.Mvvm.Core.Extensions;
using WalkingTec.Mvvm.Core.Support.Json;
using WalkingTec.Mvvm.Mvc;
using WalkingTec.Mvvm.Mvc.Admin.ViewModels.FrameworkUserVms;

namespace HengTong.Areas._Admin.Controllers
{
    [AuthorizeJwtWithCookie]
    [ApiController]
    [Route("api/_[controller]")]
    [ActionDescription("_Admin.LoginApi")]
    [AllRights]
    public class AccountController(
        ITokenService tokenService,
        ISmsAuthService smsAuthService,
        IWechatAuthService wechatAuthService,
        IMemoryCache memoryCache,
        ILogger<AccountController> logger)
        : BaseApiController
    {
        [AllowAnonymous]
        [HttpPost("[action]")]
        public async Task<IActionResult> Login([FromForm] string account, [FromForm] string password,
            [FromForm] string tenant = null, [FromForm] bool rememberLogin = false)
        {
            var user = Wtm.DoLogin(account, password, tenant);
            if (user == null)
            {
                return BadRequest(Localizer["Sys.LoginFailed"].Value);
            }

            //其他属性可以通过user.Attributes["aaa"] = "bbb"方式赋值

            Wtm.LoginUserInfo = user;

            AuthenticationProperties properties = null;
            if (rememberLogin)
            {
                properties = new AuthenticationProperties
                {
                    IsPersistent = true,
                    ExpiresUtc = DateTimeOffset.UtcNow.Add(TimeSpan.FromDays(30))
                };
            }

            var principal = Wtm.LoginUserInfo.CreatePrincipal();
            await Wtm.HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, principal, properties);
            return CheckUserInfo();
        }


        [AllowAnonymous]
        [HttpPost("[action]")]
        public async Task<Result<Token>> LoginJwt(SimpleLogin loginInfo)
        {
            var user = Wtm.DoLogin(loginInfo.Account, loginInfo.Password, loginInfo.Tenant);
            if (user == null)
            {
                // 检查用户是否存在但被停用
                var frameworkUser = await DC.Set<FrameworkUser>()
                    .AsNoTracking()
                    .FirstOrDefaultAsync(u => u.ITCode == loginInfo.Account);

                if (frameworkUser != null && !frameworkUser.IsValid)
                {
                    return new Result<Token>("账号已被停用，请联系管理员");
                }

                ModelState.AddModelError(" ", Localizer["Sys.LoginFailed"]);
                return new Result<Token>("登录失败，请检查账号或密码是否正确");
            }

            //其他属性可以通过user.Attributes["aaa"] = "bbb"方式赋值

            Wtm.LoginUserInfo = user;
            var token = await tokenService.IssueTokenAsync(Wtm.LoginUserInfo);
            return new Result<Token>()
            {
                Data = token
            };
        }


        [AllowAnonymous]
        [HttpPost("[action]")]
        [ModelFilter]
        public async Task<Result<Token>> LoginThirdParty([FromBody] LoginThirdPartyRequest request)
        {
            try
            {
                // 1. 检查请求参数
                // 2. 验证用户凭据
                var user = Wtm.DoLogin(request.account, request.password, request.Tenant);
                if (user == null)
                {
                    return new Result<Token>("用户账号或密码错误");
                }

                // 3. 检查用户状态
                var frameworkUser = await DC.Set<FrameworkUser>()
                    .AsNoTracking()
                    .FirstOrDefaultAsync(u => u.ITCode == request.account);

                if (frameworkUser == null || !frameworkUser.IsValid)
                {
                    return new Result<Token>("用户不存在或已被禁用");
                }

                // 4. 生成JWT Token
                Wtm.LoginUserInfo = user;
                var token = await tokenService.IssueTokenAsync(Wtm.LoginUserInfo);

                return new Result<Token>()
                {
                    Data = token
                };
            }
            catch (Exception ex)
            {
                return new Result<Token>($"第三方登录失败：{ex.Message}");
            }
        }


        [Public]
        [HttpGet("[action]")]
        public async Task<IActionResult> LoginRemote([FromQuery] string _remotetoken)
        {
            if (Wtm?.LoginUserInfo != null)
            {
                var principal = Wtm.LoginUserInfo.CreatePrincipal();
                await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, principal, null);
            }

            return CheckUserInfo();
        }


        [AllRights]
        [HttpGet("[action]")]
        public IActionResult SetTenant([FromQuery] string tenant)
        {
            bool rv = Wtm.SetCurrentTenant(tenant == "" ? null : tenant);
            return Ok(rv);
        }

        [AllowAnonymous]
        [HttpPost("[action]")]
        public IActionResult Reg(SimpleReg regInfo)
        {
            var exist = DC.Set<FrameworkUser>().Any(x => x.ITCode.ToLower() == regInfo.ITCode.ToLower());

            if (exist == true)
            {
                ModelState.AddModelError("ITCode", Localizer["Login.ItcodeDuplicate"]);
                return BadRequest(ModelState.GetErrorJson());
            }

            var hasuserrole = DC.Set<FrameworkRole>().Where(x => x.RoleCode == "002").FirstOrDefault();
            FrameworkUser user = new FrameworkUser
            {
                ITCode = regInfo.ITCode,
                Name = regInfo.Name,
                Password = Utils.GetMD5String(regInfo.Password),
                IsValid = true,
                PhotoId = regInfo.PhotoId,
                CreateBy = Wtm.LoginUserInfo?.ITCode,
                UpdateBy = Wtm.LoginUserInfo?.ITCode,
                CreateTime = DateTime.Now,
                UpdateTime = DateTime.Now
            };
            if (hasuserrole != null)
            {
                var userrole = new FrameworkUserRole
                {
                    UserCode = user.ITCode,
                    RoleCode = "002"
                };
                DC.Set<FrameworkUserRole>().Add(userrole);
            }

            DC.Set<FrameworkUser>().Add(user);
            DC.SaveChanges();
            return Ok();
        }


        [HttpPost("[action]")]
        [AllRights]
        [ProducesResponseType(typeof(Token), StatusCodes.Status200OK)]
        public IActionResult RefreshToken(string refreshToken)
        {
            var rv = Wtm.RefreshToken();
            if (rv == null)
            {
                return BadRequest();
            }
            else
            {
                return Ok(rv);
            }
        }

        [AllRights]
        [HttpGet("[action]")]
        public IActionResult CheckUserInfo(bool IsApi = true)
        {
            if (Wtm.LoginUserInfo == null)
            {
                return BadRequest();
            }
            else
            {
                var forapi = Wtm.LoginUserInfo;
                if (IsApi)
                {
                    forapi.SetAttributesForApi(Wtm);
                }

                forapi.DataPrivileges = null;
                forapi.FunctionPrivileges = null;
                if (forapi.Attributes == null)
                {
                    forapi.Attributes = new Dictionary<string, object>();
                }

                if (forapi.Attributes.ContainsKey("IsMainHost"))
                {
                    forapi.Attributes.Remove("IsMainHost");
                }

                if (ConfigInfo.HasMainHost && string.IsNullOrEmpty(Wtm.LoginUserInfo.TenantCode) == true)
                {
                    forapi.Attributes.Add("IsMainHost", true);
                }
                else
                {
                    forapi.Attributes.Add("IsMainHost", false);
                }

                if (forapi.Attributes.ContainsKey("IsDebug") == false)
                {
                    forapi.Attributes.Add("IsDebug", Wtm.ConfigInfo.IsQuickDebug);
                }
                else
                {
                    forapi.Attributes["IsDebug"] = Wtm.ConfigInfo.IsQuickDebug;
                }

                return Ok(forapi);
            }
        }


        [AllRights]
        [HttpPost("[action]")]
        public IActionResult ChangePassword(ChangePasswordVM vm)
        {
            if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
            {
                return Request.RedirectCall(Wtm).Result;
            }

            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState.GetErrorJson());
            }
            else
            {
                vm.DoChange();
                if (!ModelState.IsValid)
                {
                    return BadRequest(ModelState.GetErrorJson());
                }
                else
                {
                    return Ok();
                }
            }
        }

        [Public]
        [HttpGet("[action]")]
        public async Task<IActionResult> Logout()
        {
            if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
            {
                await Wtm.CallAPI<string>("mainhost", "/api/_account/logout", HttpMethodEnum.GET, new { }, 10);
                return Ok(ConfigInfo.MainHost);
            }
            else
            {
                HttpContext.Session.Clear();
                await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
                return Ok("/");
            }
        }

        [HttpGet("GetFrameworkRoles")]
        [ActionDescription("GetRoles")]
        [AllRights]
        public IActionResult GetFrameworkRoles()
        {
            if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
            {
                return Request.RedirectCall(Wtm, "/api/_account/GetFrameworkRoles").Result;
            }

            return Ok(DC.Set<FrameworkRole>().GetSelectListItems(Wtm, x => x.RoleName, x => x.RoleCode));
        }

        [HttpGet("GetFrameworkGroups")]
        [ActionDescription("GetGroups")]
        [AllRights]
        public IActionResult GetFrameworkGroups()
        {
            if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
            {
                return Request.RedirectCall(Wtm, "/api/_account/GetFrameworkGroups").Result;
            }

            return Ok(DC.Set<SysGroup>().GetSelectListItems(Wtm, x => x.GroupName, x => x.GroupCode));
        }

        [HttpGet("GetFrameworkGroupsTree")]
        [ActionDescription("GetGroupsTree")]
        [AllRights]
        public IActionResult GetFrameworkGroupsTree()
        {
            if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
            {
                return Request.RedirectCall(Wtm, "/api/_account/GetFrameworkGroupsTree").Result;
            }

            return Ok(DC.Set<SysGroup>().GetTreeSelectListItems(Wtm, x => x.GroupName, x => x.GroupCode));
        }


        [HttpGet("GetUserById")]
        [AllRights]
        public IActionResult GetUserById(string keywords)
        {
            if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
            {
                return Request.RedirectCall(Wtm, "/api/_account/GetUserById").Result;
            }

            var users = DC.Set<FrameworkUser>().Where(x => x.ITCode.ToLower().StartsWith(keywords.ToLower()))
                .GetSelectListItems(Wtm, x => x.Name + "(" + x.ITCode + ")", x => x.ITCode);
            return Ok(users);
        }

        [HttpGet("GetUserByGroup")]
        [AllRights]
        public IActionResult GetUserByGroup(string keywords)
        {
            if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
            {
                return Request.RedirectCall(Wtm, "/api/_account/GetUserByGroup").Result;
            }

            var users = DC.Set<FrameworkUserGroup>().Where(x => x.GroupCode == keywords).Select(x => x.UserCode)
                .ToList();
            return Ok(users);
        }

        [HttpGet("GetUserByRole")]
        [AllRights]
        public IActionResult GetUserByRole(string keywords)
        {
            if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
            {
                return Request.RedirectCall(Wtm, "/api/_account/GetUserByRole").Result;
            }

            var users = DC.Set<FrameworkUserRole>().Where(x => x.RoleCode == keywords).Select(x => x.UserCode).ToList();
            return Ok(users);
        }


        // 发送登录短信验证码
        [AllowAnonymous]
        [HttpPost("[action]")]
        [ModelFilter]
        public async Task<Result<string>> SendLoginSms([FromBody] SendSmsCodeRequest request)
        {
            var type = request.Type;

            switch (type)
            {
                case "login":
                case "guestBind":
                    // 验证码登录和游客绑定账户：校验手机号在FrameworkUser中是否存在
                    var phoneExists = await DC.Set<FrameworkUser>().AsNoTracking()
                        .AnyAsync(u => u.CellPhone == request.Mobile && u.IsValid);

                    if (!phoneExists)
                    {
                        return new Result<string>("手机号未在系统中注册或用户已被禁用");
                    }

                    break;

                case "changePassword":
                    // 修改密码：校验当前用户手机号是否一致
                    if (Wtm.LoginUserInfo == null)
                    {
                        return new Result<string>("用户未登录");
                    }

                    var currentUserId = Guid.Parse(Wtm.LoginUserInfo.UserId);
                    var currentUser = await DC.Set<FrameworkUser>().AsNoTracking()
                        .FirstOrDefaultAsync(u => u.ID == currentUserId);

                    if (currentUser == null || currentUser.CellPhone != request.Mobile)
                    {
                        return new Result<string>("手机号与当前用户不匹配");
                    }

                    break;

                case "changeMobile":
                    // 修改手机号：校验原手机号是否一致
                    if (Wtm.LoginUserInfo == null)
                    {
                        return new Result<string>("用户未登录");
                    }

                    if (string.IsNullOrEmpty(request.OldPhone))
                    {
                        return new Result<string>("请提供原手机号");
                    }

                    var userId = Guid.Parse(Wtm.LoginUserInfo.UserId);
                    var user = await DC.Set<FrameworkUser>().AsNoTracking()
                        .FirstOrDefaultAsync(u => u.ID == userId);

                    if (user == null)
                    {
                        return new Result<string>("用户不存在");
                    }

                    if (!string.IsNullOrEmpty(user.CellPhone) && user.CellPhone != request.OldPhone)
                    {
                        return new Result<string>("原手机号不正确");
                    }

                    // 校验新手机号是否已被使用
                    var mobileExists = await DC.Set<FrameworkUser>().AsNoTracking()
                        .AnyAsync(u => u.CellPhone == request.Mobile && u.ID != userId);

                    if (mobileExists)
                    {
                        return new Result<string>("新手机号已被其他用户使用");
                    }

                    // 校验人员档案中是否存在该手机号
                    var personExists = await DC.Set<SysPerson>().AsNoTracking()
                        .AnyAsync(u => u.Phone == request.Mobile);

                    if (personExists)
                    {
                        return new Result<string>("人员档案中已存在该手机号");
                    }

                    break;

                default:
                    return new Result<string>("不支持的验证码类型");
            }

            var result = await smsAuthService.SendCodeAsync(request.Mobile);
            return result;
        }

        // 使用短信验证码登录
        [AllowAnonymous]
        [HttpPost("[action]")]
        [ModelFilter]
        public async Task<Result<Token>> LoginBySms([FromBody] SmsLoginRequest request)
        {
            // 直接查找与手机号关联的用户
            var user = await DC.Set<FrameworkUser>()
                .AsNoTracking()
                .FirstOrDefaultAsync(u => u.CellPhone == request.Mobile && u.IsValid);

            if (user == null)
            {
                return new Result<Token>("手机号未在系统中注册或用户已被禁用");
            }

            // 验证短信验证码
            var verifyResult = smsAuthService.VerifyCode(request.Mobile, request.Code);
            if (verifyResult?.Code != 200)
            {
                return new Result<Token>(verifyResult?.Message ?? "验证码错误或已过期");
            }

            // 生成登录信息和token
            var loginInfo = new LoginUserInfo()
            {
                ITCode = user.ITCode,
                UserId = user.ID.ToString()
            };
            await loginInfo.LoadBasicInfoAsync(Wtm);
            Wtm.LoginUserInfo = loginInfo;
            var token = await tokenService.IssueTokenAsync(Wtm.LoginUserInfo);

            return new Result<Token>()
            {
                Data = token
            };
        }

        //修改手机号
        [AllRights]
        [ModelFilter]
        [HttpPost("[action]")]
        public async Task<Result<bool>> ChangeMobile([FromBody] ChangePhoneNumberRequest request)
        {
            var userId = Guid.Parse(Wtm.LoginUserInfo.UserId);
            // 获取当前用户信息
            var currentUser = await DC.Set<FrameworkUser>().AsNoTracking()
                .FirstOrDefaultAsync(u => u.ID == userId);
            if (currentUser == null)
            {
                return new Result<bool>("用户不存在");
            }

            // 校验旧手机号
            if (!string.IsNullOrEmpty(currentUser.CellPhone))
            {
                if (string.IsNullOrEmpty(request.OldPhone))
                {
                    return new Result<bool>("请提供原手机号");
                }

                if (currentUser.CellPhone != request.OldPhone)
                {
                    return new Result<bool>("原手机号不正确");
                }
            }

            // 判断新手机号是否已被使用（排除当前用户）
            var any = await DC.Set<FrameworkUser>().AsNoTracking().AnyAsync(u => u.CellPhone == request.Mobile);
            if (any) return new Result<bool>("手机号已被使用");

            // 判断人员档案中是否存在该手机号
            var anyPerson = await DC.Set<SysPerson>().AsNoTracking().AnyAsync(u => u.Phone == request.Mobile);
            if (anyPerson) return new Result<bool>("人员档案中已存在该手机号");

            // 验证新手机号验证码
            var verifyResult = smsAuthService.VerifyCode(request.Mobile, request.Code);
            if (verifyResult?.Code != 200) return new Result<bool>(verifyResult?.Message ?? "验证码错误或已过期");
            using var transaction = await DC.Database.BeginTransactionAsync();
            try
            {
                var user = await DC.Set<FrameworkUser>()
                    .FirstOrDefaultAsync(u => u.ID == userId);
                if (user == null)
                {
                    return new Result<bool>("用户不存在");
                }

                user.CellPhone = request.Mobile;
                // 增加 更新人员档案的手机号，保持一致
                await DC.Set<SysPerson>().Where(va => va.StaffNo == Wtm.LoginUserInfo.ITCode)
                    .ExecuteUpdateAsync(s => s.SetProperty(p => p.Phone, request.Mobile));
                await DC.SaveChangesAsync();
                // 提交事务
                await transaction.CommitAsync();
            }
            catch (Exception e)
            {
                // 回滚事务
                await transaction.RollbackAsync();
                return new Result<bool>($"修改手机号异常{e.Message}");
            }
            finally
            {
                await transaction.DisposeAsync();
            }

            return new Result<bool>
            {
                Code = 200,
                Message = "手机号修改成功"
            };
        }

        //修改密码，需要填写手机号验证码
        [AllRights]
        [HttpPost("[action]")]
        [ModelFilter]
        public async Task<Result<bool>> ChangePasswordBySms([FromBody] ChangePasswordBySmsRequest request)
        {
            // 密码格式验证
            if (string.IsNullOrEmpty(request.NewPassword) || request.NewPassword.Length < 6)
            {
                return new Result<bool>("新密码至少需要6位字符");
            }

            if (!System.Text.RegularExpressions.Regex.IsMatch(request.NewPassword, @"^(?=.*[A-Za-z])(?=.*\d).*$"))
            {
                return new Result<bool>("新密码必须包含字母和数字");
            }

            // 验证短信验证码
            var verifyResult = smsAuthService.VerifyCode(request.Mobile, request.Code);
            if (verifyResult?.Code != 200)
            {
                return new Result<bool>(verifyResult?.Message ?? "验证码错误或已过期");
            }

            // 获取当前用户
            var userId = Guid.Parse(Wtm.LoginUserInfo.UserId);
            var user = await DC.Set<FrameworkUser>().AsNoTracking()
                .FirstOrDefaultAsync(u => u.ID == userId);

            if (user == null)
            {
                return new Result<bool>("用户不存在");
            }

            // 验证手机号是否为当前用户绑定的手机号
            if (user.CellPhone != request.Mobile)
            {
                return new Result<bool>("手机号与当前用户不匹配");
            }

            // 如果提供了旧密码，验证旧密码
            if (!string.IsNullOrEmpty(request.OldPassword))
            {
                var oldPasswordMd5 = Utils.GetMD5String(request.OldPassword);
                if (user.Password != oldPasswordMd5)
                {
                    return new Result<bool>("原密码错误");
                }
            }

            // 更新密码
            await DC.Set<FrameworkUser>()
                .Where(u => u.ID == userId)
                .ExecuteUpdateAsync(s => s.SetProperty(u => u.Password, Utils.GetMD5String(request.NewPassword)));
            await DC.SaveChangesAsync();

            return new Result<bool>
            {
                Code = 200,
                Message = "密码修改成功"
            };
        }


        //获取微信网页登录链接
        [AllowAnonymous]
        [HttpGet("[action]")]
        public async Task<Result<string>> GetWechatLoginUrl()
        {
            var result = wechatAuthService.GetWechatLoginUrl();
            if (result.Code == 200)
            {
                return new Result<string>
                {
                    Code = 200,
                    Message = "获取微信登录链接成功",
                    Data = result.Data
                };
            }
            else
            {
                return new Result<string>("获取微信登录链接失败");
            }
        }


        // 微信网页登录回调处理
        [AllowAnonymous]
        [HttpPost("[action]")]
        [ModelFilter]
        public async Task<Result<object>> WechatLogin([FromBody] WechatLoginRequest request)
        {
            // 处理微信回调，获取用户信息
            var result = await wechatAuthService.ProcessCallback(request.Code, request.State);
            if (result.Code != 200 || result.Data == null)
            {
                return new Result<object>(result.Message ?? "微信授权失败");
            }

            var unionId = result.Data.UnionId;
            var openId = result.Data.OpenId;
            var nickname = result.Data.Nickname;
            var headImgUrl = result.Data.HeadImgUrl;

            // 查询是否已绑定系统用户
            var wechatUser = await DC.Set<SysWechatUser>()
                .AsNoTracking()
                .FirstOrDefaultAsync(x => x.UnionId == unionId || (openId != null && x.WebOpenId == openId));


            if (wechatUser == null || wechatUser.UserId == null)
            {
                var key = Uuid.NewDatabaseFriendly(Database.SqlServer).ToString().ToLower();
                memoryCache.Set($"{nameof(WechatLogin)}_{key}", result.Data, TimeSpan.FromMinutes(10));
                return new Result<object>()
                {
                    Code = 1,
                    Message = "微信未绑定系统用户",
                    Data = key
                };
            }

            // 如果已绑定，更新微信用户信息,unionId,openId,nickname,headImgUrl
            if (string.IsNullOrEmpty(wechatUser.WebOpenId) || string.IsNullOrEmpty(wechatUser.UnionId) ||
                string.IsNullOrEmpty(wechatUser.NickName) || string.IsNullOrEmpty(wechatUser.HeadImgUrl))
            {
                DC.Set<SysWechatUser>()
                    .Where(w => w.ID == wechatUser.ID).ExecuteUpdateAsync(s => s
                        .SetProperty(w => w.UnionId,
                            w => string.IsNullOrEmpty(w.UnionId) && !string.IsNullOrEmpty(unionId)
                                ? unionId
                                : w.UnionId)
                        .SetProperty(w => w.WebOpenId,
                            w => string.IsNullOrEmpty(w.WebOpenId) && !string.IsNullOrEmpty(openId)
                                ? openId
                                : w.WebOpenId)
                        .SetProperty(w => w.NickName,
                            w => string.IsNullOrEmpty(w.NickName) && !string.IsNullOrEmpty(nickname)
                                ? nickname
                                : w.NickName)
                        .SetProperty(w => w.HeadImgUrl,
                            w => string.IsNullOrEmpty(w.HeadImgUrl) && !string.IsNullOrEmpty(headImgUrl)
                                ? headImgUrl
                                : w.HeadImgUrl)).Wait();
                DC.SaveChangesAsync().Wait();
            }

            // 查找系统用户
            var user = await DC.Set<FrameworkUser>()
                .AsNoTracking()
                .FirstOrDefaultAsync(u => u.ID == wechatUser.UserId);

            if (user == null)
            {
                return new Result<object>("用户不存在");
            }

            // 如果用户已被禁用，返回错误
            if (!user.IsValid)
            {
                return new Result<object>("用户已被禁用，请联系管理员");
            }

            var loginInfo = new LoginUserInfo()
            {
                ITCode = user.ITCode,
                UserId = user.ID.ToString()
            };
            await loginInfo.LoadBasicInfoAsync(Wtm);
            Wtm.LoginUserInfo = loginInfo;
            var token = await tokenService.IssueTokenAsync(Wtm.LoginUserInfo);
            return new Result<object>()
            {
                Data = token
            };
        }

        // 微信用户绑定手机号用户
        [AllowAnonymous]
        [HttpPost("[action]")]
        [ModelFilter]
        public async Task<Result<Token>> WechatBindByMobile([FromBody] WechatBindByMobileRequest request)
        {
            if (request.Mobile == "18866668888" &&
                Wtm.ConfigInfo.AppSettings.TryGetValue("AdminCode", out var adminCode) && request.SmsCode == adminCode)
            {
                //超级管理员, 跳过验证码检查
            }
            else
            {
                // 校验短信验证码
                var verifyResult = smsAuthService.VerifyCode(request.Mobile, request.SmsCode);
                if (verifyResult?.Code != 200)
                {
                    return new Result<Token>(verifyResult?.Message ?? "验证码错误或已过期");
                }
            }

            var normalizedKey = request.WechatKey?.Trim().ToLower();
            if (string.IsNullOrEmpty(normalizedKey))
            {
                return new Result<Token>("WechatKey 不能为空");
            }

            // 优先从 memoryCache 获取 wechatUserId
            Guid? wechatUserId =
                memoryCache.Get<Guid?>($"{nameof(WechatBindByMobile)}_{request.WechatKey?.Trim().ToLower()}");

            SysWechatUser wechatUser = null;
            if (wechatUserId != null && wechatUserId != Guid.Empty)
            {
                wechatUser = await DC.Set<SysWechatUser>().AsNoTracking()
                    .FirstOrDefaultAsync(x => x.ID == wechatUserId);
            }
            else
            {
                // 兼容原有网页微信绑定逻辑
                var wechatUserInfo =
                    memoryCache.Get<WechatAuthService.WechatUserInfo>(
                        $"{nameof(WechatLogin)}_{request.WechatKey?.Trim().ToLower()}");
                if (wechatUserInfo != null)
                {
                    wechatUser = await DC.Set<SysWechatUser>().AsNoTracking().FirstOrDefaultAsync(x =>
                        x.UnionId == wechatUserInfo.UnionId ||
                        (wechatUserInfo.OpenId != null && x.WebOpenId == wechatUserInfo.OpenId));
                    if (wechatUser == null)
                    {
                        wechatUser = new SysWechatUser
                        {
                            ID = Uuid.NewDatabaseFriendly(Database.SqlServer),
                            WebOpenId = wechatUserInfo.OpenId,
                            UnionId = wechatUserInfo.UnionId,
                            NickName = wechatUserInfo.Nickname,
                            HeadImgUrl = wechatUserInfo.HeadImgUrl,
                            CreateTime = DateTime.Now
                        };
                        await DC.Set<SysWechatUser>().AddAsync(wechatUser);
                        await DC.SaveChangesAsync();
                    }
                    // 如果wechatUser 的 UnionId 或 WebOpenId 为空，则更新
                    else
                    {
                        await DC.Set<SysWechatUser>()
                            .Where(w => w.ID == wechatUser.ID)
                            .ExecuteUpdateAsync(s => s
                                .SetProperty(w => w.UnionId,
                                    w => string.IsNullOrEmpty(w.UnionId) &&
                                         !string.IsNullOrEmpty(wechatUserInfo.UnionId)
                                        ? wechatUserInfo.UnionId
                                        : w.UnionId)
                                .SetProperty(w => w.WebOpenId,
                                    w => string.IsNullOrEmpty(w.WebOpenId) &&
                                         !string.IsNullOrEmpty(wechatUserInfo.OpenId)
                                        ? wechatUserInfo.OpenId
                                        : w.WebOpenId)
                                .SetProperty(w => w.NickName,
                                    w => string.IsNullOrEmpty(w.NickName) &&
                                         !string.IsNullOrEmpty(wechatUserInfo.Nickname)
                                        ? wechatUserInfo.Nickname
                                        : w.NickName)
                                .SetProperty(w => w.HeadImgUrl,
                                    w => string.IsNullOrEmpty(w.HeadImgUrl) &&
                                         !string.IsNullOrEmpty(wechatUserInfo.HeadImgUrl)
                                        ? wechatUserInfo.HeadImgUrl
                                        : w.HeadImgUrl));
                        await DC.SaveChangesAsync();
                    }
                }
            }

            if (wechatUser == null)
            {
                return new Result<Token>("微信用户信息已过期或不存在");
            }

            // 查找手机号对应的系统用户
            var user = await DC.Set<FrameworkUser>().AsNoTracking()
                .FirstOrDefaultAsync(u => u.CellPhone == request.Mobile);
            if (user == null)
            {
                return new Result<Token>("手机号对应的用户不存在");
            }

            // 如果用户已被禁用，返回错误
            if (!user.IsValid)
            {
                return new Result<Token>("用户已被禁用，请联系管理员");
            }

            var anyAsync = await DC.Set<SysWechatUser>().AnyAsync(x => x.UserId == user.ID);
            if (anyAsync)
            {
                return new Result<Token>("该手机号已绑定微信用户");
            }

            // 绑定微信用户和系统用户
            await DC.Set<SysWechatUser>()
                .Where(x => x.ID == wechatUser.ID)
                .ExecuteUpdateAsync(s => s.SetProperty(w => w.UserId, user.ID));
            await DC.SaveChangesAsync();

            // 登录并返回 token
            var loginInfo = new LoginUserInfo()
            {
                ITCode = user.ITCode,
                UserId = user.ID.ToString()
            };
            await loginInfo.LoadBasicInfoAsync(Wtm);
            Wtm.LoginUserInfo = loginInfo;
            var token = await tokenService.IssueTokenAsync(Wtm.LoginUserInfo);
            return new Result<Token>()
            {
                Data = token
            };
        }

        // 获取登录配置信息
        [AllowAnonymous]
        [HttpGet("[action]")]
        public Result<string> GetLoginConfig()
        {
            try
            {
                // 从配置中获取是否启用短信登录和微信登录
                var enableSmsLogin = Wtm.ConfigInfo.AppSettings["EnableSmsLogin"]?.ToString()?.ToLower() == "true";
                var enableWechatLogin =
                    Wtm.ConfigInfo.AppSettings["EnableWechatLogin"]?.ToString()?.ToLower() == "true";

                // 将配置信息转换为JSON字符串
                var configInfo = JsonSerializer.Serialize(new
                {
                    EnableSmsLogin = enableSmsLogin,
                    EnableWechatLogin = enableWechatLogin
                });

                // 返回结果
                return new Result<string>
                {
                    Code = 200,
                    Message = "获取登录配置成功",
                    Data = configInfo
                };
            }
            catch (Exception ex)
            {
                return new Result<string>
                {
                    Code = 500,
                    Message = "获取登录配置失败：" + ex.Message
                };
            }
        }

        // 微信小程序登录
        [AllowAnonymous]
        [HttpPost("[action]")]
        [ModelFilter]
        public async Task<Result<object>> WechatMiniProgramLogin([FromBody] WechatMiniProgramLoginRequest request)
        {
            try
            {
                // 处理微信小程序登录，获取用户信息
                var result = await wechatAuthService.ProcessMiniProgramLogin(request.Code);
                if (result.Code != 200 || result.Data == null)
                {
                    return new Result<object>(result.Message ?? "微信小程序授权失败");
                }

                var wechatUser = result.Data;

                // 检查微信用户是否绑定系统用户
                if (wechatUser.UserId != null)
                {
                    // 查找系统用户
                    var user = await DC.Set<FrameworkUser>()
                        .AsNoTracking()
                        .FirstOrDefaultAsync(u => u.ID == wechatUser.UserId);

                    if (user == null)
                    {
                        return new Result<object>("关联的系统用户不存在");
                    }

                    // 如果用户已被禁用，返回错误
                    if (!user.IsValid)
                    {
                        return new Result<object>("用户已被禁用，请联系管理员");
                    }

                    // 生成登录信息和token
                    var loginInfo = new LoginUserInfo()
                    {
                        ITCode = user.ITCode,
                        UserId = user.ID.ToString()
                    };
                    await loginInfo.LoadBasicInfoAsync(Wtm);
                    Wtm.LoginUserInfo = loginInfo;
                    var token = await tokenService.IssueTokenAsync(Wtm.LoginUserInfo);

                    return new Result<object>()
                    {
                        Code = 200,
                        Message = "登录成功",
                        Data = token
                    };
                }
                else
                {
                    // 未绑定，缓存 wechatUserId
                    var key = Uuid.NewDatabaseFriendly(Database.SqlServer).ToString().ToLower();
                    memoryCache.Set($"{nameof(WechatBindByMobile)}_{key}", wechatUser.ID, TimeSpan.FromMinutes(10));
                    return new Result<object>
                    {
                        Code = 201,
                        Message = "当前微信用户不是系统用户，请选择游客登录还是绑定系统用户",
                        Data = new { WechatBindKey = key }
                    };
                }
            }
            catch (Exception ex)
            {
                return new Result<object>($"微信小程序登录失败：{ex.Message}");
            }
        }


        // 微信小程序游客登录
        [AllowAnonymous]
        [HttpPost("[action]")]
        [ModelFilter]
        public async Task<Result<object>> WechatMiniProgramGuestLogin([FromBody] WechatGuestLoginRequest request)
        {
            // 优先从 memoryCache 获取 wechatUserId
            Guid? wechatUserId =
                memoryCache.Get<Guid?>($"{nameof(WechatBindByMobile)}_{request.WechatKey.Trim().ToLower()}");
            if (wechatUserId == null || wechatUserId == Guid.Empty)
            {
                return new Result<object>("微信用户信息已过期或不存在");
            }

            // 检查微信用户是否存在
            var wechatUser = await DC.Set<SysWechatUser>()
                .FirstOrDefaultAsync(u => u.ID == wechatUserId);

            if (wechatUser == null)
            {
                return new Result<object>("微信用户不存在");
            }

            // 开启事务
            using var transaction = await DC.Database.BeginTransactionAsync();
            try
            {
                // 创建游客用户
                string guestName = $"guest_{DateTime.Now:yyyyMMddHHmmss}{new Random().Next(1000, 9999)}";

                // 创建游客用户
                var user = new FrameworkUser
                {
                    ID = Uuid.NewDatabaseFriendly(Database.SqlServer),
                    ITCode = guestName,
                    Name = guestName,
                    Password = Utils.GetMD5String(Uuid.NewDatabaseFriendly(Database.SqlServer).ToString()), // 加密密码
                    CreateTime = DateTime.Now,
                    CreateBy = "guest",
                };

                // 保存游客用户
                DC.Set<FrameworkUser>().Add(user);
                await DC.SaveChangesAsync();

                // 绑定游客权限，判断是否有游客999的角色，如果没有提示创建游客角色，有则绑定
                var guestRole = await DC.Set<FrameworkRole>().AsNoTracking()
                    .FirstOrDefaultAsync(r => r.RoleCode == "999");
                if (guestRole == null)
                {
                    return new Result<object>("系统未配置游客角色，请联系管理员");
                }

                var userRole = new FrameworkUserRole
                {
                    UserCode = user.ITCode,
                    RoleCode = guestRole.RoleCode,
                    CreateTime = DateTime.Now,
                    CreateBy = "guest",
                };
                DC.Set<FrameworkUserRole>().Add(userRole);
                await DC.SaveChangesAsync();

                // 绑定微信用户和游客账号
                wechatUser.UserId = user.ID;
                await DC.SaveChangesAsync();

                // 生成登录信息和token
                var loginInfo = new LoginUserInfo()
                {
                    ITCode = user.ITCode,
                    UserId = user.ID.ToString()
                };
                await loginInfo.LoadBasicInfoAsync(Wtm);
                Wtm.LoginUserInfo = loginInfo;
                var token = await tokenService.IssueTokenAsync(Wtm.LoginUserInfo);
                // 提交事务
                await transaction.CommitAsync();

                return new Result<object>
                {
                    Code = 200,
                    Message = "游客登录成功",
                    Data = token
                };
            }
            catch (Exception ex)
            {
                // 回滚事务
                await transaction.RollbackAsync();
                return new Result<object>($"微信游客登录失败：{ex.Message}");
            }
            finally
            {
                await transaction.DisposeAsync();
            }
        }


        // 微信App授权登录
        [AllowAnonymous]
        [HttpPost("[action]")]
        [ModelFilter]
        public async Task<Result<object>> WechatAppLogin([FromBody] WechatAppLoginRequest request)
        {
            try
            {
                // 处理App登录，获取用户信息
                var result = await wechatAuthService.ProcessAppLogin(request.Code);
                if (result.Code != 200 || result.Data == null)
                {
                    return new Result<object>(result.Message ?? "App授权失败");
                }

                var wechatUser = result.Data;

                // 检查微信用户是否绑定系统用户
                if (wechatUser.UserId != null)
                {
                    // 查找系统用户
                    var user = await DC.Set<FrameworkUser>()
                        .AsNoTracking()
                        .FirstOrDefaultAsync(u => u.ID == wechatUser.UserId);

                    if (user == null)
                    {
                        return new Result<object>("关联的系统用户不存在");
                    }

                    // 如果用户已被禁用，返回错误
                    if (!user.IsValid)
                    {
                        return new Result<object>("用户已被禁用，请联系管理员");
                    }

                    // 生成登录信息和token
                    var loginInfo = new LoginUserInfo()
                    {
                        ITCode = user.ITCode,
                        UserId = user.ID.ToString()
                    };
                    await loginInfo.LoadBasicInfoAsync(Wtm);
                    Wtm.LoginUserInfo = loginInfo;
                    var token = await tokenService.IssueTokenAsync(Wtm.LoginUserInfo);

                    return new Result<object>()
                    {
                        Code = 200,
                        Message = "登录成功",
                        Data = token
                    };
                }
                else
                {
                    // 未绑定，缓存用户ID
                    var key = Uuid.NewDatabaseFriendly(Database.SqlServer).ToString().ToLower();
                    memoryCache.Set($"{nameof(WechatAppLogin)}_{key}", wechatUser.ID, TimeSpan.FromMinutes(10));
                    return new Result<object>
                    {
                        Code = 201,
                        Message = "当前App用户不是系统用户，请选择游客登录还是绑定系统用户",
                        Data = new { AppBindKey = key }
                    };
                }
            }
            catch (Exception ex)
            {
                return new Result<object>($"App登录失败：{ex.Message}");
            }
        }

        // 微信App游客登录
        [AllowAnonymous]
        [HttpPost("[action]")]
        [ModelFilter]
        public async Task<Result<object>> WechatAppGuestLogin([FromBody] WechatAppGuestLoginRequest request)
        {
            try
            {
                // 从缓存中获取用户ID
                Guid? wechatUserId =
                    memoryCache.Get<Guid?>($"{nameof(WechatAppLogin)}_{request.WechatKey.Trim().ToLower()}");
                if (wechatUserId == null || wechatUserId == Guid.Empty)
                {
                    return new Result<object>("App用户信息已过期或不存在");
                }

                // 检查用户是否存在
                var wechatUser = await DC.Set<SysWechatUser>().AsNoTracking()
                    .FirstOrDefaultAsync(u => u.ID == wechatUserId);

                if (wechatUser == null)
                {
                    return new Result<object>("App用户不存在");
                }

                // 创建游客用户
                string guestName = $"app_guest_{DateTime.Now:yyyyMMddHHmmss}{new Random().Next(1000, 9999)}";

                var user = new FrameworkUser
                {
                    ID = Uuid.NewDatabaseFriendly(Database.SqlServer),
                    ITCode = guestName,
                    Name = guestName,
                    Password = Utils.GetMD5String(Uuid.NewDatabaseFriendly(Database.SqlServer).ToString()), // 加密密码
                    CreateTime = DateTime.Now,
                    CreateBy = "guest",
                };

                // 保存游客用户
                DC.Set<FrameworkUser>().Add(user);
                await DC.SaveChangesAsync();

                // 绑定用户和游客账号
                wechatUser.UserId = user.ID;
                await DC.SaveChangesAsync();

                // 生成登录信息和token
                var loginInfo = new LoginUserInfo()
                {
                    ITCode = user.ITCode,
                    UserId = user.ID.ToString()
                };
                await loginInfo.LoadBasicInfoAsync(Wtm);
                Wtm.LoginUserInfo = loginInfo;
                var token = await tokenService.IssueTokenAsync(Wtm.LoginUserInfo);

                return new Result<object>()
                {
                    Code = 200,
                    Message = "游客登录成功",
                    Data = token
                };
            }
            catch (Exception ex)
            {
                return new Result<object>($"App游客登录失败：{ex.Message}");
            }
        }

        //游客账号换绑账号
        [AllRights]
        [HttpPost("[action]")]
        [ModelFilter]
        public async Task<Result<Token>> GuestBindExistingAccount([FromBody] SmsLoginRequest request)
        {
            // 先判断FrameworkUser中是否存在手机号
            var phoneExists = await DC.Set<FrameworkUser>().AsNoTracking()
                .AnyAsync(u => u.CellPhone == request.Mobile);

            if (!phoneExists)
            {
                return new Result<Token>("手机号未在系统中注册");
            }

            // 验证短信验证码
            var verifyResult = smsAuthService.VerifyCode(request.Mobile, request.Code);
            if (verifyResult?.Code != 200)
            {
                return new Result<Token>(verifyResult?.Message ?? "验证码错误或已过期");
            }

            // 获取当前登录的游客用户
            var currentUserId = Guid.Parse(Wtm.LoginUserInfo.UserId);
            var currentUser = await DC.Set<FrameworkUser>().AsNoTracking()
                .FirstOrDefaultAsync(u => u.ID == currentUserId);

            if (currentUser == null)
            {
                return new Result<Token>("当前用户不存在");
            }

            // 检查当前用户是否为游客（通过ITCode判断是否以guest_开头）
            if (!currentUser.ITCode.StartsWith("guest_"))
            {
                return new Result<Token>("只有游客用户才能执行此操作");
            }

            // 查找手机号对应的目标用户
            var targetUser = await DC.Set<FrameworkUser>().AsNoTracking()
                .FirstOrDefaultAsync(u => u.CellPhone == request.Mobile);

            if (targetUser == null)
            {
                return new Result<Token>("手机号对应的用户不存在");
            }

            // 检查目标用户是否已被禁用
            if (!targetUser.IsValid)
            {
                return new Result<Token>("目标用户已被禁用，请联系管理员");
            }

            // 检查目标用户是否已绑定其他微信用户
            var targetUserWechatBinding = await DC.Set<SysWechatUser>().AsNoTracking()
                .FirstOrDefaultAsync(w => w.UserId == targetUser.ID);

            if (targetUserWechatBinding != null)
            {
                return new Result<Token>("该手机号对应的用户已绑定其他微信账号");
            }

            // 获取当前游客用户的微信绑定信息
            var currentWechatUser = await DC.Set<SysWechatUser>()
                .FirstOrDefaultAsync(w => w.UserId == currentUserId);

            if (currentWechatUser == null)
            {
                return new Result<Token>("当前用户未绑定微信账号");
            }

            using var transaction = await DC.Database.BeginTransactionAsync();
            try
            {
                // 1. 转移活动参与记录
                if (DC.Model.FindEntityType(typeof(SysActivityParticipation)) != null)
                {
                    await DC.Set<SysActivityParticipation>()
                        .Where(ap => ap.UserId == currentUserId)
                        .ExecuteUpdateAsync(s => s.SetProperty(ap => ap.UserId, targetUser.ID));
                }

                // 2. 转移访客申请记录
                if (DC.Model.FindEntityType(typeof(SysVisitorRecordRequestBill)) != null)
                {
                    await DC.Set<SysVisitorRecordRequestBill>()
                        .Where(va => va.UserId == currentUserId)
                        .ExecuteUpdateAsync(s => s.SetProperty(va => va.UserId, targetUser.ID)
                            .SetProperty(va => va.CreateBy, targetUser.ITCode));
                }

                // 3. 转移访客信息记录
                if (DC.Model.FindEntityType(typeof(SysVisitorInformation)) != null)
                {
                    await DC.Set<SysVisitorInformation>()
                        .Where(vi => vi.UserId == currentUserId)
                        .ExecuteUpdateAsync(s => s.SetProperty(vi => vi.UserId, targetUser.ID));
                }

                // 4. 更新微信用户绑定关系
                currentWechatUser.UserId = targetUser.ID;

                // 5. 删除游客用户相关的用户角色关系
                var userRoles = await DC.Set<FrameworkUserRole>()
                    .Where(ur => ur.UserCode == currentUser.ITCode)
                    .ToListAsync();
                if (userRoles.Any())
                {
                    DC.Set<FrameworkUserRole>().RemoveRange(userRoles);
                }

                // 6. 删除游客用户相关的用户组关系
                var userGroups = await DC.Set<FrameworkUserGroup>()
                    .Where(ug => ug.UserCode == currentUser.ITCode)
                    .ToListAsync();
                if (userGroups.Any())
                {
                    DC.Set<FrameworkUserGroup>().RemoveRange(userGroups);
                }

                // 7.删除收藏菜单数据
                var currentUserFavorites = await DC.Set<SysUserFavorite>()
                    .Where(mc => mc.UserId == currentUserId)
                    .ToListAsync();
                if (currentUserFavorites.Any())
                {
                    DC.Set<SysUserFavorite>().RemoveRange(currentUserFavorites);
                }

                // 8. 删除游客用户
                DC.Set<FrameworkUser>().Remove(currentUser);

                // 保存所有更改
                await DC.SaveChangesAsync();
                await transaction.CommitAsync();

                // 8. 生成新的登录信息和token
                var loginInfo = new LoginUserInfo()
                {
                    ITCode = targetUser.ITCode,
                    UserId = targetUser.ID.ToString()
                };
                await loginInfo.LoadBasicInfoAsync(Wtm);
                Wtm.LoginUserInfo = loginInfo;
                var token = await tokenService.IssueTokenAsync(Wtm.LoginUserInfo);

                return new Result<Token>()
                {
                    Code = 200,
                    Message = "账号绑定成功",
                    Data = token
                };
            }
            catch (Exception ex)
            {
                await transaction.RollbackAsync();
                return new Result<Token>($"绑定失败：{ex.Message}");
            }
            finally
            {
                await transaction.DisposeAsync();
            }
        }

        /// <summary>
        /// 获取用户的人员档案信息（仅主表数据）
        /// </summary>
        /// <param name="frameworkUserId">框架用户ID</param>
        /// <param name="staffNo">工号</param>
        /// <returns></returns>
        [AllRights]
        [HttpGet("[action]")]
        public async Task<Result<SysPerson>> GetPersonInfo([FromQuery] Guid? frameworkUserId = null,
            [FromQuery] string staffNo = null)
        {
            try
            {
                SysPerson person = null;

                // 如果传入了工号，直接通过工号查询
                if (!string.IsNullOrEmpty(staffNo))
                {
                    person = await DC.Set<SysPerson>()
                        .AsNoTracking()
                        .FirstOrDefaultAsync(p => p.StaffNo == staffNo);

                    if (person == null)
                    {
                        return new Result<SysPerson>("未找到对应工号的人员档案信息");
                    }

                    return new Result<SysPerson>
                    {
                        Code = 200,
                        Message = "获取人员档案信息成功",
                        Data = person
                    };
                }

                // 确定目标用户ID
                Guid targetUserId;
                if (!frameworkUserId.HasValue)
                {
                    if (Wtm.LoginUserInfo == null)
                    {
                        return new Result<SysPerson>("用户未登录");
                    }

                    targetUserId = Guid.Parse(Wtm.LoginUserInfo.UserId);
                }
                else
                {
                    targetUserId = frameworkUserId.Value;
                }

                // 查找FrameworkUser，获取关联的PersonId
                var frameworkUser = await DC.Set<FrameworkUser>()
                    .AsNoTracking()
                    .FirstOrDefaultAsync(u => u.ID == targetUserId);

                if (frameworkUser == null)
                {
                    return new Result<SysPerson>("用户不存在");
                }

                // 如果FrameworkUser直接关联了PersonId，优先使用
                if (frameworkUser.PersonId.HasValue)
                {
                    person = await DC.Set<SysPerson>()
                        .AsNoTracking()
                        .FirstOrDefaultAsync(p => p.ID == frameworkUser.PersonId.Value);
                }
                else
                {
                    // 如果没有直接关联，尝试通过工号匹配
                    person = await DC.Set<SysPerson>()
                        .AsNoTracking()
                        .FirstOrDefaultAsync(p => p.StaffNo == frameworkUser.ITCode);
                }

                if (person == null)
                {
                    return new Result<SysPerson>("未找到对应的人员档案信息");
                }

                return new Result<SysPerson>
                {
                    Code = 200,
                    Message = "获取人员档案信息成功",
                    Data = person
                };
            }
            catch (Exception ex)
            {
                return new Result<SysPerson>($"获取人员档案信息失败：{ex.Message}");
            }
        }


        /// <summary>
        /// 身份证识别接口
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [AllowAnonymous]
        [HttpPost("[action]")]
        [ModelFilter]
        public async Task<Result<IdentityCardInfo>> RecognizeIdentityCard(
            [FromBody] IdentityCardRecognitionRequest request)
        {
            if (request.ImageId == Guid.Empty)
            {
                return new Result<IdentityCardInfo>("请上传身份证图片");
            }

            if (string.IsNullOrEmpty(request.CardType))
            {
                request.CardType = "front";
            }

            if (request.CardType != "front" && request.CardType != "back")
            {
                return new Result<IdentityCardInfo>("身份证类型只能是front或back");
            }

            try
            {
                var recognitionService = HttpContext.RequestServices.GetService<IIdentityCardRecognitionService>();
                if (recognitionService == null)
                {
                    return new Result<IdentityCardInfo>("身份证识别服务未配置");
                }

                var result = await recognitionService.RecognizeAsync(request.ImageId, request.CardType);
                return result;
            }
            catch (Exception ex)
            {
                return new Result<IdentityCardInfo>($"身份证识别失败：{ex.Message}");
            }
        }


        // SSO登录入口
#if DEBUG
        [Public]
#else
[AllRights]
#endif
        [HttpGet("[action]")]
        public async Task<IActionResult> SsoLogin([FromQuery] string appid, [FromQuery] string returnUrl = null)
        {
            var requestId = Guid.NewGuid().ToString("N")[..8]; // 生成请求ID用于追踪
            logger.LogInformation(
                "SSO登录请求开始 - RequestId: {RequestId}, AppId: {AppId}, ReturnUrl: {ReturnUrl}, UserAgent: {UserAgent}",
                requestId, appid, returnUrl, Request.Headers.UserAgent.ToString());

            if (Wtm.LoginUserInfo == null)
            {
                logger.LogWarning("SSO登录失败：用户未登录 - RequestId: {RequestId}, AppId: {AppId}, IP: {IP}",
                    requestId, appid, HttpContext.Connection.RemoteIpAddress?.ToString());

                // 用户未登录，重定向到登录页面
                return Redirect($"/login?returnUrl={HttpUtility.UrlEncode(Request.GetDisplayUrl())}");
            }

            if (string.IsNullOrEmpty(appid))
            {
                logger.LogWarning("SSO登录失败：AppId参数为空 - RequestId: {RequestId}, UserId: {UserId}",
                    requestId, Wtm.LoginUserInfo.UserId);

                return BadRequest("AppId参数不能为空");
            }

            try
            {
                // 查找SSO应用配置
                var ssoApp = await DC.Set<SysSsoApplication>()
                    .AsNoTracking()
                    .FirstOrDefaultAsync(app => app.AppId == appid && app.IsActive == true);

                if (ssoApp == null)
                {
                    logger.LogWarning("SSO登录失败：无效的AppId - RequestId: {RequestId}, AppId: {AppId}, UserId: {UserId}",
                        requestId, appid, Wtm.LoginUserInfo.UserId);

                    return BadRequest("无效的AppId或应用未启用");
                }

                logger.LogInformation(
                    "找到SSO应用配置 - RequestId: {RequestId}, AppId: {AppId}, AppName: {AppName}, CallbackUrl: {CallbackUrl}",
                    requestId, appid, ssoApp.AppName, ssoApp.CallbackUrl);

                // 生成一次性令牌
                var ssoToken = Guid.NewGuid().ToString("N");
                var tokenKey = $"sso_token_{ssoToken}";

                // 缓存用户信息，设置5分钟过期
                var ssoTokenData = new SsoTokenData
                {
                    UserId = Wtm.LoginUserInfo.UserId,
                    ITCode = Wtm.LoginUserInfo.ITCode,
                    Name = Wtm.LoginUserInfo.Name,
                    AppId = appid,
                    CreateTime = DateTime.Now,
                    ReturnUrl = returnUrl
                };

                memoryCache.Set(tokenKey, ssoTokenData, TimeSpan.FromMinutes(5));

                logger.LogInformation(
                    "SSO令牌生成成功 - RequestId: {RequestId}, AppId: {AppId}, UserId: {UserId}, ITCode: {ITCode}, TokenExpiry: 5分钟",
                    requestId, appid, Wtm.LoginUserInfo.UserId, Wtm.LoginUserInfo.ITCode);

                // 构造回调URL - 支持灵活的token位置配置
                var callbackUrl = BuildCallbackUrl(ssoApp.CallbackUrl, ssoToken, returnUrl);

                logger.LogInformation(
                    "SSO登录成功，准备重定向 - RequestId: {RequestId}, AppId: {AppId}, UserId: {UserId}, CallbackUrl: {CallbackUrl}",
                    requestId, appid, Wtm.LoginUserInfo.UserId, callbackUrl);

                // 重定向到目标系统
                return Redirect(callbackUrl);
            }
            catch (Exception ex)
            {
                logger.LogError(ex,
                    "SSO登录异常 - RequestId: {RequestId}, AppId: {AppId}, UserId: {UserId}, Error: {Error}",
                    requestId, appid, Wtm.LoginUserInfo?.UserId, ex.Message);

                return BadRequest($"SSO登录失败：{ex.Message}");
            }
        }

        /// <summary>
        /// 构造回调URL，支持灵活的token位置配置
        /// </summary>
        /// <param name="baseCallbackUrl">基础回调URL</param>
        /// <param name="token">SSO令牌</param>
        /// <param name="returnUrl">返回URL</param>
        /// <returns>构造好的回调URL</returns>
        private string BuildCallbackUrl(string baseCallbackUrl, string token, string returnUrl)
        {
            try
            {
                // 检查URL中是否包含{token}占位符
                if (baseCallbackUrl.Contains("{token}"))
                {
                    // 使用占位符方式替换token
                    var result = baseCallbackUrl.Replace("{token}", token);

                    // 如果有returnUrl，添加到URL末尾
                    if (!string.IsNullOrEmpty(returnUrl))
                    {
                        var returnUrlSeparator = result.Contains("?") ? "&" : "?";
                        result += $"{returnUrlSeparator}returnUrl={HttpUtility.UrlEncode(returnUrl)}";
                    }

                    return result;
                }

                // 检查URL中是否包含{{token}}占位符（用于处理特殊字符转义的情况）
                if (baseCallbackUrl.Contains("{{token}}"))
                {
                    var result = baseCallbackUrl.Replace("{{token}}", token);

                    if (!string.IsNullOrEmpty(returnUrl))
                    {
                        var returnUrlSeparator = result.Contains("?") ? "&" : "?";
                        result += $"{returnUrlSeparator}returnUrl={HttpUtility.UrlEncode(returnUrl)}";
                    }

                    return result;
                }

                // 如果没有占位符，使用传统方式（token放在末尾）
                var tokenSeparator = baseCallbackUrl.Contains("?") ? "&" : "?";
                var callbackUrl = baseCallbackUrl + $"{tokenSeparator}token={token}";

                if (!string.IsNullOrEmpty(returnUrl))
                {
                    callbackUrl += $"&returnUrl={HttpUtility.UrlEncode(returnUrl)}";
                }

                return callbackUrl;
            }
            catch (Exception ex)
            {
                logger.LogError(ex, "构造回调URL失败，使用默认方式 - BaseUrl: {BaseUrl}, Token: {Token}",
                    baseCallbackUrl, token);

                // 异常情况下使用默认方式
                var defaultSeparator = baseCallbackUrl.Contains("?") ? "&" : "?";
                return baseCallbackUrl + $"{defaultSeparator}token={token}";
            }
        }


        // SSO令牌验证接口（供其他系统调用）
        [AllowAnonymous]
        [HttpPost("[action]")]
        public async Task<Result<SsoUserInfo>> SsoVerifyToken([FromBody] SsoVerifyRequest request)
        {
            var requestId = Guid.NewGuid().ToString("N")[..8];
            var clientIp = HttpContext.Connection.RemoteIpAddress?.ToString();
            var userAgent = Request.Headers.UserAgent.ToString();

            logger.LogInformation("SSO令牌验证请求开始 - RequestId: {RequestId}, IP: {IP}, UserAgent: {UserAgent}",
                requestId, clientIp, userAgent);

            if (string.IsNullOrEmpty(request.Token))
            {
                logger.LogWarning("SSO令牌验证失败：Token为空 - RequestId: {RequestId}, IP: {IP}",
                    requestId, clientIp);

                return new Result<SsoUserInfo>("Token不能为空");
            }

            // 记录Token的前8位用于日志追踪（不记录完整Token以确保安全）
            var tokenPrefix = request.Token.Length > 8 ? request.Token[..8] : request.Token;

            try
            {
                // 验证令牌
                var tokenKey = $"sso_token_{request.Token}";
                var ssoTokenData = memoryCache.Get<SsoTokenData>(tokenKey);

                if (ssoTokenData == null)
                {
                    logger.LogWarning(
                        "SSO令牌验证失败：Token无效或已过期 - RequestId: {RequestId}, TokenPrefix: {TokenPrefix}, IP: {IP}",
                        requestId, tokenPrefix, clientIp);

                    return new Result<SsoUserInfo>("无效的Token或Token已过期");
                }

                logger.LogInformation(
                    "SSO令牌验证成功，找到用户信息 - RequestId: {RequestId}, TokenPrefix: {TokenPrefix}, AppId: {AppId}, UserId: {UserId}, ITCode: {ITCode}, TokenAge: {TokenAge}秒",
                    requestId, tokenPrefix, ssoTokenData.AppId, ssoTokenData.UserId, ssoTokenData.ITCode,
                    (DateTime.Now - ssoTokenData.CreateTime).TotalSeconds);

                // 令牌验证成功后立即删除（一次性使用）
                memoryCache.Remove(tokenKey);

                logger.LogInformation("SSO令牌已销毁（一次性使用） - RequestId: {RequestId}, TokenPrefix: {TokenPrefix}",
                    requestId, tokenPrefix);

                // 获取用户详细信息
                var userId = Guid.Parse(ssoTokenData.UserId);
                var user = await DC.Set<FrameworkUser>()
                    .AsNoTracking()
                    .FirstOrDefaultAsync(u => u.ID == userId);

                if (user == null || !user.IsValid)
                {
                    logger.LogWarning(
                        "SSO令牌验证失败：用户不存在或已禁用 - RequestId: {RequestId}, UserId: {UserId}, UserExists: {UserExists}, IsValid: {IsValid}",
                        requestId, ssoTokenData.UserId, user != null, user?.IsValid);

                    return new Result<SsoUserInfo>("用户不存在或已被禁用");
                }

                // 返回用户信息
                var userInfo = new SsoUserInfo
                {
                    UserId = user.ID.ToString(),
                    ITCode = user.ITCode,
                    Name = user.Name,
                    CellPhone = user.CellPhone,
                    LoginTime = DateTime.Now
                };

                logger.LogInformation(
                    "SSO令牌验证完成，返回用户信息 - RequestId: {RequestId}, AppId: {AppId}, UserId: {UserId}, ITCode: {ITCode}, Name: {Name}, IP: {IP}",
                    requestId, ssoTokenData.AppId, user.ID, user.ITCode, user.Name, clientIp);

                return new Result<SsoUserInfo>
                {
                    Code = 200,
                    Message = "验证成功",
                    Data = userInfo
                };
            }
            catch (Exception ex)
            {
                logger.LogError(ex,
                    "SSO令牌验证异常 - RequestId: {RequestId}, TokenPrefix: {TokenPrefix}, IP: {IP}, Error: {Error}",
                    requestId, tokenPrefix, clientIp, ex.Message);

                return new Result<SsoUserInfo>($"令牌验证失败：{ex.Message}");
            }
        }

        // 第三方系统单点登录接口
        [AllowAnonymous]
        [HttpPost("[action]")]
        [ModelFilter]
        public async Task<IActionResult> ThirdPartySsoLogin([FromBody] ThirdPartySsoRequest request)
        {
            var requestId = Guid.NewGuid().ToString("N")[..8]; // 生成请求ID用于追踪
            logger.LogInformation(
                "第三方系统SSO登录请求 - RequestId: {RequestId}, AppId: {AppId}, IP: {IP}",
                requestId, request.AppId, HttpContext.Connection.RemoteIpAddress?.ToString());

            try
            {
                // 验证参数
                if (string.IsNullOrEmpty(request.EncryptedITCode) || string.IsNullOrEmpty(request.AppId))
                {
                    return BadRequest("加密工号或AppId不能为空");
                }

                // 解密工号
                //string itCode = DecryptITCode(request.EncryptedITCode, request.AppId);
                string itCode = request.EncryptedITCode; // 临时直接使用，实际项目中应解密
                if (string.IsNullOrEmpty(itCode))
                {
                    logger.LogWarning("工号解密失败 - RequestId: {RequestId}, AppId: {AppId}", requestId, request.AppId);
                    return BadRequest("工号解密失败或无效");
                }

                // 查找用户
                var user = await DC.Set<FrameworkUser>()
                    .AsNoTracking()
                    .FirstOrDefaultAsync(u => u.ITCode == itCode && u.IsValid);

                if (user == null)
                {
                    logger.LogWarning("用户不存在或已禁用 - RequestId: {RequestId}, ITCode: {ITCode}", requestId, itCode);
                    return BadRequest("用户不存在或已被禁用");
                }

                // 查找SSO应用配置
                var ssoApp = await DC.Set<SysSsoApplication>()
                    .AsNoTracking()
                    .FirstOrDefaultAsync(app => app.AppId == request.AppId && app.IsActive == true);

                if (ssoApp == null)
                {
                    logger.LogWarning("无效的AppId - RequestId: {RequestId}, AppId: {AppId}", requestId, request.AppId);
                    return BadRequest("无效的AppId或应用未启用");
                }

                // 创建登录信息
                var loginInfo = new LoginUserInfo()
                {
                    ITCode = user.ITCode,
                    UserId = user.ID.ToString()
                };
                await loginInfo.LoadBasicInfoAsync(Wtm);
                Wtm.LoginUserInfo = loginInfo;

                // 生成SSO令牌
                var ssoToken = Guid.NewGuid().ToString("N");
                var tokenKey = $"sso_token_{ssoToken}";

                // 缓存用户信息
                var ssoTokenData = new SsoTokenData
                {
                    UserId = user.ID.ToString(),
                    ITCode = user.ITCode,
                    Name = user.Name,
                    AppId = request.AppId,
                    CreateTime = DateTime.Now
                };

                memoryCache.Set(tokenKey, ssoTokenData, TimeSpan.FromMinutes(5));

                logger.LogInformation(
                    "第三方SSO令牌生成成功 - RequestId: {RequestId}, AppId: {AppId}, UserId: {UserId}, ITCode: {ITCode}",
                    requestId, request.AppId, user.ID, user.ITCode);

                // 构造回调URL
                var callbackUrl = BuildCallbackUrl(ssoApp.CallbackUrl, ssoToken, null);

                // 记录重定向信息
                logger.LogInformation(
                    "准备重定向到目标系统 - RequestId: {RequestId}, AppId: {AppId}, CallbackUrl: {CallbackUrl}",
                    requestId, request.AppId, callbackUrl);

                // 重定向到目标系统
                return Redirect(callbackUrl);
            }
            catch (Exception ex)
            {
                logger.LogError(ex,
                    "第三方系统SSO登录异常 - RequestId: {RequestId}, AppId: {AppId}, Error: {Error}",
                    requestId, request.AppId, ex.Message);

                return BadRequest($"SSO登录失败：{ex.Message}");
            }
        }

        // 解密工号方法
        private string DecryptITCode(string encryptedITCode, string appId)
        {
            try
            {
                // 根据不同的AppId可以使用不同的解密方式
                var ssoApp = DC.Set<SysSsoApplication>()
                    .AsNoTracking()
                    .FirstOrDefault(app => app.AppId == appId);

                if (ssoApp == null) return null;

                // 假设在SysSsoApplication表中存储了密钥
                // string secretKey = ssoApp.SecretKey;

                string secretKey = "SecretKey";
                // 实现解密逻辑，这里使用AES解密示例
                // 实际项目中应根据与第三方系统协商的加密算法实现
                using (var aes = Aes.Create())
                {
                    // 从Base64获取字节
                    byte[] cipherBytes = Convert.FromBase64String(encryptedITCode);

                    // 前16字节是IV，后面是加密数据
                    byte[] iv = new byte[16];
                    byte[] cipher = new byte[cipherBytes.Length - 16];

                    Array.Copy(cipherBytes, 0, iv, 0, 16);
                    Array.Copy(cipherBytes, 16, cipher, 0, cipher.Length);

                    // 设置解密参数
                    aes.Key = System.Text.Encoding.UTF8.GetBytes(secretKey.PadRight(32).Substring(0, 32));
                    aes.IV = iv;

                    // 创建解密器
                    using (var decryptor = aes.CreateDecryptor())
                    using (var ms = new MemoryStream(cipher))
                    using (var cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read))
                    using (var reader = new StreamReader(cs))
                    {
                        return reader.ReadToEnd();
                    }
                }
            }
            catch (Exception ex)
            {
                logger.LogError(ex, "解密工号失败: {Error}", ex.Message);
                return null;
            }
        }

        /// <summary>
        /// SSO 回调接口，用于验证 token 并创建用户会话
        /// </summary>
        [AllowAnonymous]
        [HttpGet("[action]")]
        public async Task<IActionResult> SsoCallback([FromQuery] string token, [FromQuery] string returnUrl = null)
        {
            var requestId = Guid.NewGuid().ToString("N")[..8];
            logger.LogInformation(
                "SSO回调请求开始 - RequestId: {RequestId}, TokenPrefix: {TokenPrefix}, ReturnUrl: {ReturnUrl}",
                requestId, token?.Length > 8 ? token[..8] : token, returnUrl);

            try
            {
                // 验证令牌
                var ssoTokenKey = $"sso_token_{token}"; // 修改变量名避免冲突
                var ssoTokenData = memoryCache.Get<SsoTokenData>(ssoTokenKey);

                if (ssoTokenData == null)
                {
                    logger.LogWarning("SSO回调失败：令牌无效或过期 - RequestId: {RequestId}", requestId);
                    return BadRequest("无效的Token或Token已过期");
                }

                // 移除缓存中的令牌数据(一次性使用)
                memoryCache.Remove(ssoTokenKey);

                // 查找用户
                var userId = Guid.Parse(ssoTokenData.UserId);
                var user = await DC.Set<FrameworkUser>()
                    .AsNoTracking()
                    .FirstOrDefaultAsync(u => u.ID == userId);

                if (user == null || !user.IsValid)
                {
                    logger.LogWarning("SSO回调失败：用户不存在或已禁用 - RequestId: {RequestId}", requestId);
                    return BadRequest("用户不存在或已被禁用");
                }

                logger.LogInformation("SSO回调Token验证成功 - RequestId: {RequestId}, UserId: {UserId}, ITCode: {ITCode}",
                    requestId, user.ID, user.ITCode);

                // 创建登录信息
                var loginInfo = new LoginUserInfo()
                {
                    ITCode = user.ITCode,
                    UserId = user.ID.ToString()
                };
                await loginInfo.LoadBasicInfoAsync(Wtm);
                Wtm.LoginUserInfo = loginInfo;

                // 生成JWT令牌 - 注意这里变量名改为jwtToken
                var jwtToken = await tokenService.IssueTokenAsync(Wtm.LoginUserInfo);

                // 确定重定向目标URL
                string targetUrl = string.IsNullOrEmpty(ssoTokenData.ReturnUrl) ? "/" : ssoTokenData.ReturnUrl;
                if (!string.IsNullOrEmpty(returnUrl))
                {
                    targetUrl = returnUrl;
                }

                // 构建包含token的前端URL，根据tokenService返回类型调整获取AccessToken的方式
                string frontendUrl;

                // 根据实际Token对象的属性名进行访问（可能是AccessToken或access_token）
                string accessToken = jwtToken.AccessToken; // 根据实际返回类型调整

                if (targetUrl.Contains("#"))
                {
                    // 针对hash路由的特殊处理
                    int hashIndex = targetUrl.IndexOf("#");
                    string baseUrl = targetUrl.Substring(0, hashIndex);
                    string hashPart = targetUrl.Substring(hashIndex);
    
                    if (baseUrl.Contains("?"))
                        frontendUrl = $"{baseUrl}&access_token={accessToken}{hashPart}";
                    else
                        frontendUrl = $"{baseUrl}?access_token={accessToken}{hashPart}";
                }
                else if (targetUrl.Contains("?"))
                {
                    frontendUrl = $"{targetUrl}&access_token={accessToken}";
                }
                else
                {
                    frontendUrl = $"{targetUrl}?access_token={accessToken}";
                }

                logger.LogInformation(
                    "SSO回调登录成功，准备重定向 - RequestId: {RequestId}, UserId: {UserId}, ReturnUrl: {ReturnUrl}",
                    requestId, user.ID, targetUrl);

                return Redirect(frontendUrl);
            }
            catch (Exception ex)
            {
                logger.LogError(ex, "SSO回调处理异常 - RequestId: {RequestId}, Error: {Error}", requestId, ex.Message);
                return BadRequest($"SSO回调处理失败：{ex.Message}");
            }
        }


        /// <summary>
        /// 人像照片验证接口
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [HttpPost("[action]")]
        [ModelFilter]
        [AllowAnonymous]
        //[AllRights]
        public async Task<Result<string>> ValidatePortrait([FromBody] ValidatePortraitRequest request)
        {
            if (request.ImageId == Guid.Empty)
            {
                return new Result<string>("图片ID不能为空");
            }

            try
            {
                var portraitService = HttpContext.RequestServices.GetService<IPortraitPhotoService>();
                if (portraitService == null)
                {
                    return new Result<string>("人像检测服务未配置");
                }

                var result = await portraitService.ValidatePortraitAsync(request.ImageId);

                if (result.Code != 200)
                {
                    return new Result<string>(result.Message ?? "人像检测失败");
                }

                return new Result<string>
                {
                    Code = 200,
                    Message = "人像检测成功",
                    Data = result.Data
                };
            }
            catch (Exception ex)
            {
                return new Result<string>($"人像检测异常：{ex.Message}");
            }
        }

        /// <summary>
        /// 生成证件照接口
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [HttpPost("[action]")]
        [ModelFilter]
        [AllowAnonymous]
        public async Task<Result<Guid>> GenerateIdPhoto([FromBody] GenerateIdPhotoRequest request)
        {
            if (request.ImageId == Guid.Empty)
            {
                return new Result<Guid>("图片ID不能为空");
            }

            try
            {
                var portraitService = HttpContext.RequestServices.GetService<IPortraitPhotoService>();
                if (portraitService == null)
                {
                    return new Result<Guid>("人像照片服务未配置");
                }

                var result = await portraitService.GenerateIdPhotoAsync(
                    request.ImageId,
                    request.BackgroundColor, // 不传默认红底
                    request.Size);

                if (result.Code != 200)
                {
                    return new Result<Guid>(result.Message ?? "证件照生成失败");
                }

                return new Result<Guid>
                {
                    Code = 200,
                    Message = "证件照生成成功",
                    Data = result.Data // 这里返回的是新的图片ID
                };
            }
            catch (Exception ex)
            {
                return new Result<Guid>($"证件照生成异常：{ex.Message}");
            }
        }
    }


    public class SimpleLogin
    {
        public string Account { get; set; }
        public string Password { get; set; }
        public string Tenant { get; set; }

        public string RemoteToken { get; set; }
    }

    public class ThirdPartySsoRequest
    {
        [Required(ErrorMessage = "加密工号不能为空")] public string EncryptedITCode { get; set; }

        [Required(ErrorMessage = "AppId不能为空")] public string AppId { get; set; }
    }


    public class SimpleReg
    {
        [Display(Name = "_Admin.Account")]
        [Required(ErrorMessage = "Validate.{0}required")]
        [StringLength(50, ErrorMessage = "Validate.{0}stringmax{1}")]
        public string ITCode { get; set; }

        [Display(Name = "_Admin.Name")]
        [Required(ErrorMessage = "Validate.{0}required")]
        [StringLength(50, ErrorMessage = "Validate.{0}stringmax{1}")]
        public string Name { get; set; }

        [Display(Name = "Login.Password")]
        [Required(AllowEmptyStrings = false)]
        [StringLength(50, ErrorMessage = "Validate.{0}stringmax{1}")]
        public string Password { get; set; }

        [Display(Name = "_Admin.Photo")] public Guid? PhotoId { get; set; }
    }

    public class LoginThirdPartyRequest
    {
        [Required(ErrorMessage = "账号不能为空")] public string account { get; set; }

        [Required(ErrorMessage = "密码不能为空")] public string password { get; set; }

        public string Tenant { get; set; }
    }

    // SSO令牌数据
    public class SsoTokenData
    {
        public string UserId { get; set; }
        public string ITCode { get; set; }
        public string Name { get; set; }
        public string AppId { get; set; }
        public DateTime CreateTime { get; set; }
        public string ReturnUrl { get; set; }
    }

    // SSO用户信息
    public class SsoUserInfo
    {
        public string UserId { get; set; }
        public string ITCode { get; set; }
        public string Name { get; set; }
        public string CellPhone { get; set; }
        public DateTime LoginTime { get; set; }
    }

    // SSO令牌验证请求（简化版）
    public class SsoVerifyRequest
    {
        [Required(ErrorMessage = "Token不能为空")] public string Token { get; set; }
    }
}